home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Archives
/
ForCLI
/
SecureDel42_1.lha
/
SecureDel42_1
/
SecureDelete.c
< prev
Wrap
C/C++ Source or Header
|
1995-08-10
|
6KB
|
209 lines
/*
* $VER: SecureDelete.c 42.1 (10.8.95)
*
* by Bruce M. Simpson <bsimpson@touchdwn.demon.co.uk>
*
* A 'secure' deletion program for files on any filesystem. It works by
* overwriting the data of the file itself, and making sure the buffers are
* forced out to disk. Later versions will probably incorporate a special
* algorithm designed to wipe out all traces of the file's data from the
* magnetic medium. The old file header does NOT get deleted, as this is
* up to the filesystem, however file headers can be removed from Amiga
* filesystem volumes by using a tool such as ReOrg, which is admittedly
* overkill, but there's no 100% kosher way to eliminate the file headers
* unless the handler specifically a custom packet for doing so...
*
* I could make this remove every single trace of a file from an AmigaDOS
* volume, but hey, life's too short, and anyway I see the blocks getting
* overwrittem when I check up using DiskX and SnoopDos, so I'm satisfied.
*
* THIS PROGRAM HAS NO WARRANTY EXPRESSED OR IMPLIED. ANY DAMAGE CAUSED
* TO FILES OR COMPUTER SYSTEMS BY RUNNING THS PROGRAM IS NOT THE AUTHOR'S
* RESPONSIBILITY. USE THIS PROGRAM AT YOUR OWN RISK.
*
*/
#include <exec/types.h>
#include <exec/alerts.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/dos.h>
#include "debug.h"
static const TEXT verstag[] = "$VER: SecureDelete 42.1 (10.8.85)\0";
static const TEXT ProgName[] = "SecureDelete";
static const TEXT cmdtemplate[] = "FILE/A";
#define OS_LIB_VERSION 37L /* release 2 or better */
#define EMPTY_MEM_SIZE 512 /* kludgy - may look up device blocksize later */
long __builtin_getreg(int);
__regargs ULONG main (void)
{
register struct ExecBase *SysBase = (*((struct ExecBase **)4L));
register struct DosLibrary *DOSBase = NULL;
register struct Library *UtilityBase = NULL;
struct Process *myProcess = (struct Process *) FindTask(NULL);
struct FileInfoBlock *fib = NULL;
struct RDArgs *rdargs = NULL;
struct DevProc *devproc = NULL;
STRPTR filename;
ULONG rc = RETURN_FAIL;
ULONG currblk;
ULONG numblocks;
ULONG remainder;
BPTR fh = NULL;
BOOL ovfail = TRUE;
void *emptybuf = NULL;
if (!( DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", OS_LIB_VERSION )))
{
D(bug("%s: Couldn't open %s\n",ProgName,"dos.library"));
Alert( AG_OpenLib | AO_DOSLib );
myProcess->pr_Result2 = ERROR_INVALID_RESIDENT_LIBRARY;
goto cleanup;
}
if (!( UtilityBase = OpenLibrary("utility.library", OS_LIB_VERSION )))
{
D(bug("%s: Couldn't open %s\n",ProgName,"utility.library"));
Alert( AG_OpenLib | AO_UtilityLib );
SetIoErr( ERROR_INVALID_RESIDENT_LIBRARY );
PrintFault( ERROR_INVALID_RESIDENT_LIBRARY, ProgName);
goto cleanup;
}
if (!( rdargs = ReadArgs(cmdtemplate, (LONG *) &filename, NULL )))
{
D(bug("%s: Invalid command line arguments\n",ProgName));
PrintFault(IoErr(), ProgName);
goto cleanup;
}
/* of course, what we are about to do is only valid under a filesystem */
/* you can do it on a handler but that makes no sense... */
if (!IsFileSystem(filename))
{
Printf("%s: Device of '%s' is not a FileSystem\n",ProgName);
rc = RETURN_ERROR; goto cleanup;
}
if (!( fh = Open(filename, MODE_OLDFILE )))
{
D(bug("%s: Couldn't open file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
rc = RETURN_ERROR; goto cleanup;
}
if (!( fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, TAG_DONE )))
{
D(bug("%s: Couldn't allocate FileInfoBlock\n",ProgName));
PrintFault(IoErr(), ProgName);
goto cleanup;
}
if (!(ExamineFH(fh,fib)))
{
D(bug("%s: Couldn't examine opened file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
goto cleanup;
}
if (!( emptybuf = AllocMem(EMPTY_MEM_SIZE, MEMF_PUBLIC | MEMF_CLEAR )))
{
D(bug("%s: Couldn't allocate empty memory block\n",ProgName));
SetIoErr(ERROR_NO_FREE_STORE);
PrintFault(ERROR_NO_FREE_STORE, ProgName);
goto cleanup;
}
/* use explicit long math calls to remain pure (compiler bug workaround) */
numblocks = UDivMod32(fib->fib_Size,EMPTY_MEM_SIZE);
remainder = __builtin_getreg(1);
/* overwrite each block */
if (numblocks)
for (currblk = 0; currblk < numblocks; currblk++)
if (Write(fh,emptybuf,EMPTY_MEM_SIZE) != EMPTY_MEM_SIZE)
{
D(bug("%s: Error overwriting file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
rc = RETURN_ERROR; break;
}
/* did we fail whilst in the loop? */
if (currblk == numblocks) ovfail = FALSE;
/* overwrite remaining bytes */
if (remainder && !ovfail)
if (Write(fh,emptybuf,remainder) != remainder)
{
D(bug("%s: Error overwriting file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
rc = RETURN_ERROR;
}
/* try and close the file */
if (!Close(fh))
{
D(bug("%s: Error closing file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
ovfail = TRUE; rc = RETURN_ERROR;
}
fh = NULL;
/* only attempt to delete file if overwriting successful */
if (!ovfail)
{
if (!DeleteFile(filename))
{
/* DeleteFile() failed */
D(bug("%s: Error deleting file '%s'\n",ProgName,filename));
PrintFault(IoErr(), ProgName);
rc = RETURN_ERROR;
}
else
{
/* everything succeeded... */
Printf("%s: '%s' deleted securely\n",ProgName,filename);
rc = RETURN_OK; /* flag success */
}
}
if (devproc = GetDeviceProc(filename,devproc))
{
/* always flush filesystem if we got this far */
if (!DoPkt(devproc->dvp_Port,ACTION_FLUSH,NULL,NULL,NULL,NULL,NULL))
{
D(bug("%s: Failed to flush filesystem\n",ProgName));
Printf("%s: Failed to flush filesystem\n",ProgName);
rc = RETURN_WARN; /* warn user that FLUSH failed */
}
FreeDeviceProc(devproc);
}
else
{
D(bug("%s: GetDeviceProc() failed on '%s'\n",ProgName,filename));
Printf("%s: Failed to flush filesystem\n",ProgName);
rc = RETURN_WARN; /* warn user that FLUSH failed */
}
cleanup:
if (emptybuf) FreeMem(emptybuf,EMPTY_MEM_SIZE);
if (fib) FreeDosObject(DOS_FIB,(APTR)fib);
if (fh) Close(fh);
if (rdargs) FreeArgs(rdargs);
if (UtilityBase) CloseLibrary(UtilityBase);
if (DOSBase) CloseLibrary((struct Library *)DOSBase);
return(rc);
}